package com.cskaoyan.javase.oop1._11block._3static;

/**
 * @description: 静态代码块
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * 静态代码块: 声明在成员位置的代码块,但是要使用static关键字去修饰代码块
 * 声明方式: static{}
 * 静态代码块的作用: 在类加载的过程中,会被执行的代码块.你可以把静态代码块当成一个在类加载过程中
 *      会自动调用的一个静态方法,所以静态代码块经常用于给静态成员变量赋值
 *
 * 总结一下目前学习的给静态成员变量赋值的方式:
 *   a,类加载过程当中的赋值方式
 *      1,默认初始化
 *      2,显式赋值
 *      3,静态代码块赋值
 *   b,创建对象过程当中赋值方式
 *      1,构造器
 *      2,构造代码块
 *      3,普通成员方法
 *
 * 在类加载过程当中赋值,首先默认初始化具有默认值仍然是第一步的
 *      显式赋值和静态代码块赋值仍然是按照代码的书写顺序执行
 * 当然,还是不建议把静态代码块写在声明的上面,正常情况下还是写在下面比较合适
 *
 *
 * 静态代码块的用途:
 *      静态代码块的使用场景是比较少的,普遍用来给静态成员变量赋值
 *      一般来说,当静态的成员变量需要比较复杂的赋值方式时,使用静态代码块
 *
 * 需要注意的是：
 * - 静态代码块和静态成员一样，不能在里面调用非静态
 * - 除非是静态成员变量需要很复杂的初始化代码，否则没太大必要使用，直接显式赋值就行
 * - 静态代码块和静态成员变量的定义顺序，也会影响到静态成员变量的最终取值
 *   - 所以应该永远将静态代码块放在静态成员变量的定义下面
 *
 * - 构造代码块可以给静态成员变量赋值，静态代码块却不能给普通成员代码块赋值
 *   - 若构造代码块和静态代码块同时给一个静态成员变量赋值
 *     - 它们在代码中的顺序，并不会对结果造成影响
 *   - 因为静态代码块总是先于构造代码块执行
 *
 * 补充一点:
 *      在我们实际开发中,我们经常用静态代码块来测试类加载的顺序
 *      静态代码块的执行在类加载的最后一步--初始化
 *      静态代码块没有执行并不完全说明类加载没有进行,而是说明它没有进行完整的类加载
 *      类加载是有可能执行一半的
 *
 */
public class Demo {
    static {
        System.out.println("Demo");
    }

    public static void main(String[] args) {
        System.out.println(Animal.color);
    }
}

class Animal {
    static {
        System.out.println("Animal");
    }

    int age;

    static String color = "白色";

    static {
        color = "黑色";
        Animal a = new Animal();
        System.out.println(a.age);
    }

}
